package secret

import (
	"errors"
	"fmt"

	"gitee.com/micro-plat/sas/sas/modules/const/enum"
	"gitee.com/micro-plat/sas/sas/modules/const/models"
	"gitee.com/micro-plat/sas/sas/modules/util"
	per "gitee.com/micro-plat/sas/sas/modules/util/permission"

	"github.com/micro-plat/lib4go/db"
	"github.com/micro-plat/lib4go/errs"
	"github.com/micro-plat/lib4go/security/rsa"
)

//RSASecret 对象
type RSASecret struct {
	db *DBSecret
}

//NewRSASecret 创建对象
func NewRSASecret() *RSASecret {
	return &RSASecret{
		db: NewDBSecret(),
	}
}

//Generate RSA密钥生成
func (s *RSASecret) Generate(euid string, item *models.Item) (res *RSAResponse, err error) {

	uid, err := s.generateCheck(euid)
	if err != nil {
		return
	}

	if item.RsaType == "" {
		item.RsaType = rsa.PKCS8
	}
	if item.RsaBits <= 0 {
		item.RsaBits = 1024
	}
	//获取RSA密钥对
	pubKey, priKey, err := util.GenRsaKey(item.RsaType, item.RsaBits)
	if err != nil {
		return
	}

	if uid == "" {
		//数据不存在时创建新数据并添加RSA密钥
		uid, err = s.db.addRSASecret(euid, pubKey, priKey, item.RsaType, item.RsaBits, item.ExpireTime)
	} else {
		//数据存在时在原数据上添加RSA密钥
		err = s.db.updateRSASecret(uid, pubKey, priKey, item.RsaType, item.RsaBits, item.ExpireTime)
	}
	if err != nil {
		return
	}

	info, err := s.db.GetPermission(euid)
	if err != nil {
		return
	}

	deleteCache(euid)
	return buildRSAResponse(info)
}

func (s *RSASecret) generateCheck(euid string) (uid string, err error) {

	info, err := s.db.GetPermission(euid)
	if err != nil || info == nil {
		return
	}

	//密钥已存在
	if info.GetString(enum.GetNameByValue(enum.RSA)) != "" {
		err = errs.NewError(enum.ERR_ExistsSecret, fmt.Errorf("要生成的密钥已存在，若要修改该类型密钥请调用set或reset服务"))
		return
	}

	//密钥不存在，获取uid
	uid = info.GetString("uid")
	return
}

//Get RSA密钥获取
func (s *RSASecret) Get(euid string) (res *RSAResponse, err error) {

	//获取数据
	info, err := GetSecretCache(euid)
	if err != nil {
		return
	}

	//构造返回参数
	return buildRSAResponse(info)
}

//Reset RSA密钥重置
func (s *RSASecret) Reset(euid string, item *models.Item) (res *RSAResponse, err error) {

	//获取数据
	info, err := s.existCheck(euid, enum.RSA)
	if err != nil {
		return
	}
	pkcsType := item.RsaType
	if pkcsType == "" {
		pkcsType = rsa.PKCS8
	}
	if item.RsaBits <= 0 {
		item.RsaBits = 1024
	}
	//获取RSA密钥对
	pubKey, priKey, err := util.GenRsaKey(pkcsType, item.RsaBits)
	if err != nil {
		return
	}

	//保存密钥
	uid := info.GetString("uid")
	if err := s.db.updateRSASecret(uid, pubKey, priKey, item.RsaType, item.RsaBits, item.ExpireTime); err != nil {
		return nil, err
	}

	//构造返回参数
	deleteCache(euid)

	return s.Get(euid)
}

func (s *RSASecret) existCheck(euid string, sType int) (info db.QueryRow, err error) {

	info, err = s.db.GetPermission(euid)
	if err != nil {
		return
	}

	//不存在数据
	if info == nil {
		err = errs.NewError(enum.ERR_NotExits, fmt.Errorf("数据不存在"))
		return
	}

	//密钥不存在
	if info.GetString(enum.GetNameByValue(sType)) == "" {
		err = errs.NewError(enum.ERR_NotExitsSecretType, fmt.Errorf("该类型密钥不存在"))
		return
	}

	return
}

//Enable RSA密钥启用
func (s *RSASecret) Enable(euid string) (res *RSAResponse, err error) {

	//获取数据
	info, err := s.existCheck(euid, enum.RSA)
	if err != nil {
		return
	}

	//RSA密钥启用
	uid := info.GetString("uid")
	if !per.Check(info.GetInt("status"), enum.RSA) {
		if err := s.db.enableSecret(uid, enum.RSA); err != nil {
			return nil, err
		}
	}

	//构造返回参数
	deleteCache(euid)
	return newRSAResponse(info, "0")
}

//Disable RSA密钥禁用
func (s *RSASecret) Disable(euid string) (res *RSAResponse, err error) {

	//获取数据
	info, err := s.existCheck(euid, enum.RSA)
	if err != nil {
		return
	}

	//RSA密钥禁用
	uid := info.GetString("uid")
	if per.Check(info.GetInt("status"), enum.RSA) {
		if err := s.db.disableSecret(uid, enum.RSA); err != nil {
			return nil, err
		}
	}

	//构造返回参数
	deleteCache(euid)
	return newRSAResponse(info, "1")
}

//Set RSA密钥设置
func (s *RSASecret) Set(euid string, item *models.Item) (res *RSAResponse, err error) {
	pubKey := item.RsaPublicSecret
	priKey := item.RsaPrivateSecret

	if pubKey == "" || priKey == "" {
		err = errors.New("pub_key,pri_key:不能设置为空")
		return
	}
	if item.RsaType == "" {
		item.RsaType = rsa.PKCS8
	}

	if item.RsaBits <= 0 {
		item.RsaBits = 1024
	}

	//获取数据
	info, err := s.existCheck(euid, enum.RSA)
	if err != nil {
		return
	}

	//去除密钥头尾和换行符等
	priKey = rsa.RemovePriKeyFix(priKey, item.RsaType)
	pubKey = rsa.RemovePubKeyFix(pubKey)
	//保存密钥
	uid := info.GetString("uid")
	if err := s.db.updateRSASecret(uid, pubKey, priKey, item.RsaType, item.RsaBits, item.ExpireTime); err != nil {
		return nil, err
	}

	//构造返回参数
	deleteCache(euid)
	return s.Get(euid)
}
